Deep Dive into OpenBSD's `pf` Firewall

OpenBSD’s `pf` (Packet Filter) is one of the most powerful and flexible firewalling tools available today. Known for its simplicity, security, and performance, `pf` is widely used in OpenBSD and FreeBSD systems. This tutorial provides an in-depth look at `pf`, covering its features, configuration, and practical use cases.

What is `pf`?

`pf` is a stateful packet filter that was introduced in OpenBSD 3.0 as a replacement for IPFilter. It is designed to be simple, secure, and efficient, making it ideal for a wide range of use cases, from personal firewalls to enterprise-grade network security.

Key Features of `pf`

`pf` offers a rich set of features that make it a versatile firewalling tool:

  • Stateful Filtering: Tracks the state of connections and allows related packets automatically.
  • NAT and Redirection: Supports Network Address Translation (NAT) and port redirection.
  • Traffic Shaping: Includes `altq` for bandwidth management and prioritization.
  • High Availability: Supports `CARP` (Common Address Redundancy Protocol) for failover and redundancy.
  • Logging: Provides detailed logging of packet activity using `pflog`.
  • Table Management: Allows dynamic and efficient management of IP address lists using tables.

Getting Started with `pf`

To use `pf`, you need to configure its rules in the `pf.conf` file, which is typically located in `/etc/pf.conf`. The basic structure of `pf.conf` includes:

  • Macros: Define reusable variables for IP addresses, ports, etc.
  • Tables: Define dynamic lists of IP addresses.
  • Options: Configure global settings for `pf`.
  • Rules: Define filtering, NAT, and redirection rules.

Enabling `pf`

To enable `pf`, use the following commands:


# Enable pf
pfctl -e
# Load the configuration file
pfctl -f /etc/pf.conf

Basic Configuration Example

Here’s a simple example of a `pf.conf` file:


# Macros
ext_if = "em0"  # External interface
int_if = "em1"  # Internal interface
local_net = "192.168.1.0/24"

# Options
set skip on lo  # Skip filtering on the loopback interface

# NAT
nat on $ext_if from $local_net to any -> ($ext_if)

# Filtering Rules
block all
pass out on $ext_if proto tcp to port 80 keep state
pass in on $int_if from $local_net to any keep state

Explanation

  • Macros: Define variables for interfaces and networks to simplify the configuration.
  • Options: Skip filtering on the loopback interface to avoid blocking internal traffic.
  • NAT: Enable NAT for traffic from the internal network to the external interface.
  • Rules: Block all traffic by default, then allow specific traffic (e.g., HTTP and internal traffic).

Advanced Features

Once you’re comfortable with the basics, you can explore `pf`’s advanced features:

1. Traffic Shaping with `altq`

`altq` allows you to manage bandwidth and prioritize traffic. Example:


altq on $ext_if cbq bandwidth 100Mb queue { http, ssh }
queue http bandwidth 80% cbq(default)
queue ssh bandwidth 20%
pass out on $ext_if proto tcp to port 80 keep state queue http
pass out on $ext_if proto tcp to port 22 keep state queue ssh

2. High Availability with `CARP`

`CARP` provides redundancy by allowing multiple firewalls to share a virtual IP address. Example:


vhid 1 pass "sharedsecret"
pass in on $ext_if proto carp keep state

3. Dynamic Tables

Tables allow you to manage large lists of IP addresses efficiently. Example:


table  persist
block in quick from 

You can dynamically add or remove IPs using `pfctl`:


pfctl -t blocked_ips -T add 192.168.1.100
pfctl -t blocked_ips -T delete 192.168.1.100

Logging and Monitoring

`pf` provides robust logging and monitoring capabilities:

  • Logging: Use `pflog` to log packet activity. Example:
  • 
    pass in log on $ext_if proto tcp to port 22
    
        
  • Monitoring: Use `tcpdump` to view logs in real-time:
  • 
    tcpdump -n -e -ttt -i pflog0
    
        

Practical Use Cases

Here are some common use cases for `pf`:

  • Home Firewall: Secure your home network with NAT and basic filtering rules.
  • Web Server Protection: Allow only HTTP/HTTPS traffic and block everything else.
  • VPN Gateway: Use `pf` to secure VPN traffic and manage access to internal resources.
  • Intrusion Prevention: Block malicious IPs dynamically using tables and external threat feeds.

Best Practices

To maximize the effectiveness of your `pf` firewall, follow these best practices:

  • Principle of Least Privilege: Block all traffic by default and allow only what is necessary.
  • Use Macros and Tables: Simplify your configuration and make it easier to manage.
  • Enable Logging: Log all critical rules to monitor traffic and troubleshoot issues.
  • Test Configurations: Test your `pf.conf` file in a staging environment before deploying it to production.
  • Keep Rules Organized: Group related rules together and use comments to document your configuration.

Conclusion

OpenBSD’s `pf` is a powerful and versatile firewalling tool that combines simplicity with advanced features. Whether you’re securing a home network or managing an enterprise-grade firewall, `pf` provides the flexibility and performance you need. In the next tutorial, we’ll explore FreeBSD’s `ipfw` firewall and its unique features. Stay tuned!

 

 

Check out some Bands on Bandcamp.com. Seven Times Refined by Altogether Steve and the Mercenaries, Crazy Fingers (Vancouver 1991), Flying Butt Pliers, and Hammy Ham Hands.

Proudly powered by a Text Editor, an IDE, an SFTP client, some Internet searches, and more recently help from some AI.

2025 dispelled.ca end of file.